package com.chaodriod.common.system

import android.annotation.TargetApi
import android.app.Activity
import android.app.KeyguardManager
import android.app.admin.DevicePolicyManager
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.PowerManager
import com.chaodriod.common.utils.ALog
import com.chaodriod.common.utils.Utils

/**
 * Created by 72byte on 2017/9/21.
 * 屏蔽电源键
 */

class ScreenReceiver : BroadcastReceiver() {

    companion object {

        private const val KEY_REASON = "reason"
        private const val REASON_SCREEN_TURN_ON = "TurnScreenOn"
        private const val REASON_SCREEN_KEEP_ON = "KeepScreenOn"
        private const val REASON_SCREEN_KEEP_OFF = "KeepScreenOff"
        private const val REASON_POWER_KEY = "lock"
        private const val REASON_POWER_KEY_LONG = "globalactions"
        //保持亮屏的时间
//        private const val mKeepScreeenTime: Long = 1000 * 60 * 10
        private const val mKeepScreeenTime: Long = 60000

        /**
         * mScreenOffTime:收到 ACTION_SCREEN_OFF的时间
         * mPowerKeyTime:收到 ACTION_CLOSE_SYSTEM_DIALOGS=lock 的时间
         * 手动按电源键关屏：先收到 ACTION_SCREEN_OFF 的时间，后收到ACTION_CLOSE_SYSTEM_DIALOGS=lock，时间差不超过1秒
         * 自动休眠关屏：先收到 ACTION_SCREEN_OFF 的时间，后收到ACTION_CLOSE_SYSTEM_DIALOGS=lock，时间差超过5秒
         * 自动解锁将无法收到 ACTION_CLOSE_SYSTEM_DIALOGS 广播，放弃此方案
         * 新方案：屏蔽系统自动休眠，一直保持亮屏，只有电源键、睡眠模式和 checkout 可以触发 ACTION_SCREEN_OFF
         */
        private var mScreenOffTime: Long = 0
        private var mPowerKeyTime: Long = 0

        //获取keyguardManager 控制 WakeLock
        internal val powerManager: PowerManager by lazy {
            Utils.getContext().getSystemService(Context.POWER_SERVICE) as PowerManager
        }
        /**
         * 各种类型的 wacklock 对 CPU 、屏幕、键盘的影响：
         * PARTIAL_WAKE_LOCK:保持 CPU 运转，屏幕和键盘灯有可能是关闭的。
         * SCREEN_DIM_WAKE_LOCK：保持 CPU 运转，允许保持屏幕显示但有可能是灰的，允许关闭键盘灯
         * SCREEN_BRIGHT_WAKE_LOCK：保持 CPU 运转，允许保持屏幕高亮显示，允许关闭键盘灯
         * FULL_WAKE_LOCK：保持 CPU 运转，保持屏幕高亮显示，键盘灯也保持亮度
         * 上面四种正常唤醒锁，在屏幕关闭之后并不能打开照明
         * ACQUIRE_CAUSES_WAKEUP：这个标志会使屏幕或和键盘立即打开，并且一直保持。
         * 此时短按电源键收不到 ACTION_CLOSE_SYSTEM_DIALOGS 广播
         * ON_AFTER_RELEASE：设置了这个标志，当wakelock释放时用户activity计时器会被重置，导致照明持续一段时间。
         * 如果你在wacklock条件中循环，这个可以用来减少闪烁
         */
        //点亮屏幕并且一直保持，此时短按电源键收不到 ACTION_CLOSE_SYSTEM_DIALOGS 广播
        internal val mScreenTurnOn: PowerManager.WakeLock by lazy {
            powerManager.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP or PowerManager.SCREEN_BRIGHT_WAKE_LOCK, REASON_SCREEN_TURN_ON)
        }
        //点亮屏幕后，改用 mScreenKeepOn 保持屏幕亮度
        val mScreenKeepOn: PowerManager.WakeLock by lazy {
            powerManager.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP or PowerManager.SCREEN_BRIGHT_WAKE_LOCK, REASON_SCREEN_KEEP_ON)
        }
        //睡眠模式或者用回手动关屏，保持CPU运行
        internal val mScreenKeepOff: PowerManager.WakeLock by lazy {
            powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, REASON_SCREEN_KEEP_OFF)
        }

        //获取keyguardManager控制锁屏
        internal val keyguardManager: KeyguardManager by lazy {
            Utils.getContext().getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
        }
        internal val mKeyLock: KeyguardManager.KeyguardLock by lazy {
            keyguardManager.newKeyguardLock("unLock")
        }

        //锁屏需要获取DevicePolicyManager
        internal val policyManager: DevicePolicyManager by lazy {
            Utils.getContext().getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
        }
        internal val componentName: ComponentName by lazy {
            ComponentName(Utils.getContext(), DeviceAdminReceiver::class.java)
        }

        // 点亮屏幕
        fun turnScreenOn() {
            ALog.e("")
            mScreenTurnOn.setReferenceCounted(true)
            mScreenTurnOn.acquire(1000)     //1秒后自动释放
        }

        // 点亮屏幕
        fun turnScreenOn(time: Long) {
            ALog.e("")
            mScreenTurnOn.setReferenceCounted(true)
            mScreenTurnOn.acquire(time)     //time ms 后自动释放
        }

        fun keepScreenOnTime() {
            // 点亮屏幕
//            turnScreenOn()
            ALog.e("")
            mScreenKeepOn.setReferenceCounted(true)
            mScreenKeepOn.acquire(mKeepScreeenTime)     //10分钟后释放锁
            if (mScreenKeepOff.isHeld) {
                mScreenKeepOff.release()
            }
        }

        fun keepScreenOnLong() {
            // 点亮屏幕
//            turnScreenOn()
            ALog.e("")
            mScreenKeepOn.setReferenceCounted(false)
            mScreenKeepOn.acquire()
            if (mScreenKeepOff.isHeld) {
                mScreenKeepOff.release()
            }
        }

        fun keepScreenOff() {
            ALog.e("")
            mScreenKeepOff.setReferenceCounted(false)
            mScreenKeepOff.acquire()
            if (mScreenKeepOn.isHeld) {
                mScreenKeepOn.release()
            }
        }

        @TargetApi(Build.VERSION_CODES.FROYO)
        fun lockScreen(activity: Activity) {
            /*
             * 假如先判断是否有权限，如果没有则调用activeManage()，然后立即锁屏，最后再finish()。
             * 这样做是有问题的，因为activeManage()可能还在等待另一个Activity的结果，那么此时依然没有权限却
             * 执行了lockNow()，这样就出错了。 处理方法有2个：
             * 1、是重写OnActivityResult()函数，在里面判断是否获取权限成功，是则锁屏并finish()
             * 否则继续调用activeManage()获取权限（这样激活后立即锁屏，效果很好）
             * 2、不重写OnActivityResult()函数，第一次获取权限后不锁屏而立即finish()，这样从理论上说也可能
             * 失败，可能权限还没获取好就finish了（这样激活后就回到桌面，还得再按一次锁屏才能锁） 综上推荐第一种方法。
             */
            // 判断是否有锁屏权限，若有则立即锁屏并结束自己，若没有则获取权限
            if (policyManager.isAdminActive(componentName)) {
                //睡眠模式下，锁屏并且保持CPU运行
                mScreenKeepOff.acquire()
                policyManager.lockNow()// 锁屏
            } else {
                activeManage(activity) //获取权限
            }
        }

        /**
         * 获取权限
         */
        private fun activeManage(activity: Activity) {
            // 启动设备管理(隐式Intent) - 在AndroidManifest.xml中设定相应过滤器
            val intent = Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN)
            // 权限列表
            intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName)
            // 描述(additional explanation) 在申请权限时出现的提示语句
            intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
                    "激活后就能一键锁屏了")
            activity.startActivityForResult(intent, 999)
        }
    }

    override fun onReceive(context: Context, intent: Intent) {
        //新方案：屏蔽系统自动休眠，一直保持亮屏，只有电源键、睡眠模式和 checkout 可以触发 ACTION_SCREEN_OFF
        if (intent.action.equals(Intent.ACTION_SCREEN_OFF, ignoreCase = true)) {
            ALog.e("Intent.ACTION_SCREEN_OFF")
            keepScreenOff()
//            mScreenOffTime = System.currentTimeMillis()
//            if (mPowerKeyTime > 0) {
//                handlerWakeLock()
//            }
        }
        val reason = intent.getStringExtra("reason")
        if (intent.action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS, ignoreCase = true)) {
            ALog.e("Intent.ACTION_CLOSE_SYSTEM_DIALOGS : " + intent.getStringExtra(KEY_REASON))
//            if (reason == REASON_POWER_KEY) {
//                mPowerKeyTime = System.currentTimeMillis()
//                if (mScreenOffTime > 0) {
//                    handlerWakeLock()
//                }
//            }
            //屏蔽电源长按键的方法
//            if (reason == REASON_POWER_KEY_LONG) {
//                val myIntent = Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)
//                myIntent.putExtra("myReason", true)
//                context.sendOrderedBroadcast(myIntent, null)
//            }
//            if (intent.extras != null && intent.extras.getBoolean("myReason")) {
//                this.abortBroadcast()
//            }
        }

        if (intent.action.equals(Intent.ACTION_SCREEN_ON, ignoreCase = true)) {
            ALog.e("Intent.ACTION_SCREEN_ON")
            mKeyLock.disableKeyguard()  //解锁锁屏界面

        }

        if (intent.action.equals(Intent.ACTION_USER_PRESENT, ignoreCase = true)) {
            ALog.e("Intent.ACTION_USER_PRESENT")
        }
    }


}
